package com.lxp.base.net.okhttp;

import com.google.gson.Gson;
import com.lxp.base.log.Log;
import com.lxp.base.net.self.BaseCallBack;
import com.lxp.base.net.self.IBaseHttp;

import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.FlowableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.CacheControl;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Dispatcher;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by lxp on 2017/6/4.
 */

public class OkHttpImpl<T> implements IBaseHttp<T> {
    private OkHttpClient mClient;
    private Request.Builder mRequestBuilder;
    private static final MediaType MEDIA_OBJECT_STREAM = MediaType.parse("application/octet-stream");

    public OkHttpImpl() {
        mClient = OkHttpHelper.getInstance();
        mRequestBuilder = new Request.Builder();
    }

    @Override
    public IBaseHttp appendHeaders(Map<String, String> headers) {
        Set<String> keys = headers.keySet();
        for (String key : keys) {
            mRequestBuilder.addHeader(key, headers.get(key));
        }
        return this;
    }

    @Override
    public IBaseHttp setUrl(String url) {
        this.mRequestBuilder.url(url);
        return this;
    }

    @Override
    public IBaseHttp appendParams(Map<String, Object> params) {
        if (null != params && !params.isEmpty()) {
            MultipartBody.Builder bodyBuilder = new MultipartBody.Builder();
            bodyBuilder.setType(MultipartBody.FORM);
            for (String key : params.keySet()) {
                Object value = params.get(key);
                if (value instanceof String) {
                    String v = value.toString();
                    bodyBuilder.addFormDataPart(String.valueOf(key), String.valueOf(v));
                    //上传文件
                } else if (value instanceof File) {
                    File file = (File) value;
                    RequestBody fileBody = RequestBody.create(MEDIA_OBJECT_STREAM, file);
                    bodyBuilder.addFormDataPart(key, file.getName(), fileBody);
                } else {
                    String v = value.toString();
                    bodyBuilder.addFormDataPart(key, v);
                }
            }
            mRequestBuilder.post(bodyBuilder.build());
        }
        return this;
    }

    @Override
    public IBaseHttp setTag(Object tag) {
        this.mRequestBuilder.tag(tag);
        return this;
    }

    @Override
    public IBaseHttp isCache(boolean isCache, int cacheTime) {
        //CacheControl.FORCE_CACHE强制使用缓存
        if (isCache && cacheTime > 0) {
            //缓存10分钟
            mRequestBuilder.cacheControl(new CacheControl.Builder().maxStale(cacheTime, TimeUnit.MILLISECONDS).build());
        } else {
            //FORCE_NETWORK 不使用缓存
            mRequestBuilder.cacheControl(CacheControl.FORCE_NETWORK);
        }
        return this;
    }


    @Override
    public void cancel(Object tag) {
        Dispatcher dispatcher = mClient.dispatcher();
        for (Call call : dispatcher.queuedCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
        for (Call call : dispatcher.runningCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
    }

    @Override
    public void get(final BaseCallBack callBack) {
        Flowable.create((FlowableOnSubscribe<String>) flowableEmitter -> {
                    Request request = mRequestBuilder.build();
                    mClient.newCall(request).enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            flowableEmitter.onError(e);
                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            String bodyStr = response.body().string();
                            if (response.isSuccessful()) {
                                flowableEmitter.onNext(bodyStr);
                            } else {
                                flowableEmitter.onError(new Throwable(bodyStr));
                            }
                        }
                    });
                }
                , BackpressureStrategy.ERROR).subscribeOn(Schedulers.newThread())//子线程运行
                .observeOn(AndroidSchedulers.mainThread())//UI线程执行
                .subscribe(new Subscriber<String>() {
                               private Subscription mSubscription;

                               @Override
                               public void onSubscribe(Subscription s) {
                                   s.request(Long.MAX_VALUE);
                                   mSubscription = s;
                               }

                               @Override
                               public void onNext(String s) {
                                   Log.json(s);
                                   callBack.isSuccess(s, null);
                                   mSubscription.cancel();
                               }

                               @Override
                               public void onError(Throwable t) {
                                   Log.e(t, "接口异常\n");
                                   callBack.isFail(t);
                               }

                               @Override
                               public void onComplete() {

                               }
                           }

                );
    }

    @Override
    public void post(BaseCallBack callBack) {
        get(callBack);
    }

}
